Skip to content

Remove unused/unreachable code from ops #18964

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from

Conversation

jbrockmendel
Copy link
Member

Add TODO comments for questionable cases.

  • passes git diff upstream/master -u -- "*.py" | flake8 --diff

@codecov
Copy link

codecov bot commented Dec 28, 2017

Codecov Report

Merging #18964 into master will increase coverage by 0.02%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #18964      +/-   ##
==========================================
+ Coverage   91.57%   91.59%   +0.02%     
==========================================
  Files         150      150              
  Lines       48941    48909      -32     
==========================================
- Hits        44817    44798      -19     
+ Misses       4124     4111      -13
Flag Coverage Δ
#multiple 89.95% <100%> (+0.02%) ⬆️
#single 41.77% <90%> (+0.02%) ⬆️
Impacted Files Coverage Δ
pandas/core/ops.py 93.94% <100%> (+3.7%) ⬆️
pandas/plotting/_converter.py 65.22% <0%> (-1.74%) ⬇️
pandas/core/computation/expressions.py 93.27% <0%> (-1.69%) ⬇️
pandas/core/indexes/datetimelike.py 97.04% <0%> (-0.02%) ⬇️
pandas/util/testing.py 84.95% <0%> (+0.21%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c19bdc9...5b704fa. Read the comment docs.

@@ -721,6 +686,10 @@ def safe_na_op(lvalues, rvalues):
return na_op(lvalues, rvalues)
except Exception:
if isinstance(rvalues, ABCSeries):
# TODO: This case is not hit in tests. For it to be hit would
# require `right` to be an object such that right.values
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

limit the comments to useful info, 'screwup' does not fall in this category

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is more a suggestion that we get rid of this block.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that. but this is public code, you can certainly say 'this should be removed'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok with removing this code here

@@ -731,7 +700,9 @@ def safe_na_op(lvalues, rvalues):
lambda x: op(x, rvalues))
raise

def wrapper(left, right, name=name, na_op=na_op):
def wrapper(left, right, na_op=na_op):
# TODO: `na_op` does not belong in Series.__{op}__ signature. But this
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0.21.1:

>>> inspect.getargspec(pd.Series.__add__)
ArgSpec(args=['left', 'right', 'name', 'na_op'], varargs=None, keywords=None, defaults=('__add__', <function na_op at 0x10c4b7d70>))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and so what?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... and there's precedent for caring about signatures that make sense, especially in super-commonly-used user-facing methods.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't worry about it anyway, I found a way to get na_op and name out of the signature.


wrapper.__name__ = name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is hit in tests, yes? (the name of the wrapper)

Copy link
Member Author

@jbrockmendel jbrockmendel Dec 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0.21.1:

>>> pd.Series.__sub__
<unbound method Series.wrapper>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah that's not right. can you add tests for this? (I believe we have a suite of tests for the stat methods, so prob just need to add these on).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We recently made similar tests for Index comparison method names in tests.indexes.test_base, I don't see much else to that effect. I'll put something together.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

def wrapper(left, right, name=name, na_op=na_op):
def wrapper(left, right, na_op=na_op):
# TODO: `na_op` does not belong in Series.__{op}__ signature. But this
# is needed here for closure/namespace purposes ATM.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add doc-strings. this is extremely useful to future readers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any docstring added here would become the docstring for pd.Series.__foo__, which I doubt is what you have in mind here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, so just a comment then which describes the input & types

@@ -1371,23 +1339,6 @@ def f(self, other):

def _arith_method_PANEL(op, name, str_rep=None, fill_zeros=None,
default_axis=None, **eval_kwargs):
# copied from Series na_op above, but without unnecessary branch for
# non-scalar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, not super concerned about Panel things generally.

@jreback jreback added the Clean label Dec 28, 2017
def _validate(self, lvalues, rvalues, name):
if self.is_datetime_lhs:
return self._validate_datetime(lvalues, rvalues, name)
elif self.is_timedelta_lhs:
return self._validate_timedelta(name)
elif self.is_offset_lhs:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this offset case not possible? (it may not be tested) but is it possible?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because _TimeOp is only used if is_datetime_lhs or is_timedelta_lhs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, can you doc-string things a bit, will help future readers.

@pep8speaks
Copy link

pep8speaks commented Dec 29, 2017

Hello @jbrockmendel! Thanks for updating the PR.

Cheers ! There are no PEP8 issues in this Pull Request. 🍻

Comment last updated on January 01, 2018 at 16:47 Hours UTC


wrapper.__name__ = name
if hasattr(operator, name) and callable(getattr(operator, name)):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh? what is this for

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You asked for generic docstrings for these ops. These are about as generic as they get. But there is no e.g. operator.rfloordiv, so we have to condition.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, but this is an obscure way of doing this. I would rather actually construct a proper doc-string here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll remove this, can consider docstrings out of scope for this PR.

@@ -354,24 +356,25 @@ class _TimeOp(_Op):
"""
Wrapper around Series datetime/time/timedelta arithmetic operations.
Generally, you should use classmethod ``_Op.get_op`` as an entry point.

This is only reached in cases where either `self.is_datetime_lhs`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need the single back ticks

self.is_timedelta_lhs = is_timedelta64_dtype(lvalues)
self.is_datetime64_lhs = is_datetime64_dtype(lvalues)
self.is_datetime64tz_lhs = is_datetime64tz_dtype(lvalues)
self.is_datetime_lhs = (self.is_datetime64_lhs or
self.is_datetime64tz_lhs)
self.is_integer_lhs = left.dtype.kind in ['i', 'u']
self.is_floating_lhs = left.dtype.kind == 'f'
assert left.dtype.kind not in ['i', 'u', 'f'], left
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert one of the is_* e.g.
asert self.is_timedelta_lhs or self is_datetime_lhs

@@ -517,15 +489,16 @@ def _convert_to_array(self, values, name=None, other=None):
elif isinstance(values, pd.DatetimeIndex):
values = values.to_series()
# datetime with tz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix this comment

values = pd.DatetimeIndex(values)
# datetime array with tz
elif is_datetimetz(values):
if isinstance(values, ABCSeries):
values = values._values
elif not (isinstance(values, (np.ndarray, ABCSeries)) and
is_datetime64_dtype(values)):
# TODO: This is not hit in tests. What case is it intended
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think can remove this case if change 492 to
elif isinstance(ovalues, (datetime.datetime, np.datetime64))

In [4]: np.datetime64('2013-01-01T00:00:00.000000000')
Out[4]: numpy.datetime64('2013-01-01T00:00:00.000000000')

In [5]: isinstance(np.datetime64('2013-01-01T00:00:00.000000000'), np.ndarray)
Out[5]: False

In [6]: isinstance(np.array(np.datetime64('2013-01-01T00:00:00.000000000')), np.ndarray)
Out[6]: True

In [7]: np.array(np.datetime64('2013-01-01T00:00:00.000000000'))
Out[7]: array(1356998400000000000, dtype='datetime64[ns]')

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good.

@@ -721,6 +686,10 @@ def safe_na_op(lvalues, rvalues):
return na_op(lvalues, rvalues)
except Exception:
if isinstance(rvalues, ABCSeries):
# TODO: This case is not hit in tests. For it to be hit would
# require `right` to be an object such that right.values
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok with removing this code here


wrapper.__name__ = name
if hasattr(operator, name) and callable(getattr(operator, name)):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, but this is an obscure way of doing this. I would rather actually construct a proper doc-string here

@@ -857,6 +826,8 @@ def wrapper(self, other, axis=None):
# Validate the axis parameter
if axis is not None:
self._get_axis_number(axis)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes should change (but agreed may not be hit in tests)

@jreback jreback added Timedelta Timedelta data type Datetime Datetime data dtype labels Dec 31, 2017
@jreback
Copy link
Contributor

jreback commented Jan 1, 2018

closing in favor of #19024

@jreback jreback closed this Jan 1, 2018
@jreback jreback added this to the No action milestone Jan 4, 2018
@jbrockmendel jbrockmendel deleted the ops_cleanup branch January 23, 2018 04:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Clean Datetime Datetime data dtype Timedelta Timedelta data type
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants